package cn.thornbird.orgsync.controller;

import cn.thornbird.orgsync.annotation.CurrentUser;
import cn.thornbird.orgsync.entity.CertificateDetail;
import cn.thornbird.orgsync.entity.status.AppType;
import cn.thornbird.orgsync.exception.BadRequestException;
import cn.thornbird.orgsync.exception.ForbiddenException;
import cn.thornbird.orgsync.exception.NotFoundException;
import cn.thornbird.orgsync.helper.*;
import cn.thornbird.orgsync.model.AppUserData;
import cn.thornbird.orgsync.model.Result;
import cn.thornbird.orgsync.model.TreeData;
import cn.thornbird.orgsync.model.UserData;
import cn.thornbird.orgsync.model.combined.CertificateObject;
import cn.thornbird.orgsync.service.CertificateService;
import cn.thornbird.orgsync.vo.record.CertificateDetailRecord;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RestController
@RequestMapping(value = "/api/certificate")
@Api
public class CertificateController {

    private final CertificateService certificateService;

    private final StringRedisTemplate redisTemplate;

    @Value("${application.server-ips}")
    private String serverIps;

    public CertificateController(CertificateService certificateService, StringRedisTemplate redisTemplate) {
        this.certificateService = certificateService;
        this.redisTemplate = redisTemplate;
    }

    @GetMapping("serverIps")
    public Result<String> getServerIps() {
        return Result.success(serverIps);
    }

    @GetMapping("find/{id}")
    public Result<CertificateObject> find(@CurrentUser @ApiIgnore UserData userData, @PathVariable String id)
            throws ForbiddenException, NotFoundException {
        return Result.success(certificateService.find(userData, id));
    }

    @GetMapping("query")
    public Result<List<CertificateObject>> query(@CurrentUser @ApiIgnore UserData userData) {
        return Result.success(certificateService.query(userData));
    }

    @PostMapping("add/{companyId}")
    public Result<CertificateObject> add(@CurrentUser @ApiIgnore UserData userData, @PathVariable String companyId)
            throws BadRequestException, ForbiddenException, NotFoundException {
        return Result.success(certificateService.add(userData, companyId));
    }

    @PostMapping("save/{id}")
    public Result<CertificateObject> save(@CurrentUser @ApiIgnore UserData userData, @PathVariable String id,
                                          @RequestBody @Valid List<CertificateDetailRecord> details)
            throws BadRequestException, ForbiddenException, NotFoundException {
        return Result.success(certificateService.save(userData, id, details));
    }

    @DeleteMapping("delete/{id}")
    public Result<CertificateObject> delete(@CurrentUser @ApiIgnore UserData userData, @PathVariable String id)
            throws ForbiddenException, NotFoundException {
        return Result.success(certificateService.delete(userData, id));
    }

    @PostMapping("test")
    public Result<List<TreeData>> test(@CurrentUser @ApiIgnore UserData userData,
                                       @RequestBody @Valid CertificateDetailRecord certificateDetail)
            throws ForbiddenException {
        List<TreeData> treeDataList = new ArrayList<>();
        if (certificateDetail.getAppType() == null || StringUtils.isEmpty(certificateDetail.getData())) {
            return Result.success(treeDataList);
        }

        userData.checkAuthority(UserData.AUTHORIZED);
        AppHelper helper = AppHelper.getHelper(certificateDetail.getAppType());
        if (helper != null) {
            helper.initialize(redisTemplate, certificateDetail.getData());
            treeDataList = helper.getOrganizationTree();
        }
        return Result.success(treeDataList);
    }

    @PostMapping("test/{companyId}/{appType}")
    public Result<List<TreeData>> test(@CurrentUser @ApiIgnore UserData userData,
                                       @PathVariable String companyId, @PathVariable AppType appType)
            throws ForbiddenException, NotFoundException {
        List<TreeData> treeDataList = new ArrayList<>();
        userData.checkAuthority(UserData.AUTHORIZED);
        CertificateDetail certificateDetail = certificateService.findDetail(userData, companyId, appType);
        if (certificateDetail != null) {
            AppHelper helper = AppHelper.getHelper(appType);
            if (helper != null) {
                helper.initialize(redisTemplate, certificateDetail.getData());
                treeDataList = helper.getOrganizationTree();
            }
        }
        return Result.success(treeDataList);
    }

    @PostMapping("test/{departmentId}")
    public Result<List<AppUserData>> testUsers(@CurrentUser @ApiIgnore UserData userData,
                                               @PathVariable String departmentId,
                                               @RequestBody @Valid CertificateDetailRecord certificateDetail)
            throws ForbiddenException {
        List<AppUserData> users = new ArrayList<>();
        if (certificateDetail.getAppType() == null || StringUtils.isEmpty(certificateDetail.getData())) {
            return Result.success(users);
        }

        userData.checkAuthority(UserData.AUTHORIZED);
        AppHelper helper = AppHelper.getHelper(certificateDetail.getAppType());
        if (helper != null) {
            helper.initialize(redisTemplate, certificateDetail.getData());
            users = helper.getUsersByDepartmentId(departmentId);
        }

        Collections.sort(users, (u1, u2) -> {
            Long index1 = null;
            Long index2 = null;
            if (u1.getDepartments() != null && u1.getDepartments().containsKey(departmentId)) {
                index1 = u1.getDepartments().get(departmentId).getOrder();
            }
            if (u2.getDepartments() != null && u2.getDepartments().containsKey(departmentId)) {
                index2 = u2.getDepartments().get(departmentId).getOrder();
            }
            index1 = index1 == null ? 0 : index1;
            index2 = index2 == null ? 0 : index2;
            return index1 - index2 > 0 ? 1 : (index1 - index2 < 0 ? -1 : 0);
        });
        return Result.success(users);
    }

}
